home *** CD-ROM | disk | FTP | other *** search
/ PC World 2007 September / PCWorld_2007-09_cd.bin / system / ntfs / ntfsundelete.exe / {app} / pyue / ue_runtime.pyc (.txt) < prev   
Python Compiled Bytecode  |  2007-07-23  |  33KB  |  1,097 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. import sys
  5. import traceback
  6. import thread
  7. import os
  8. import os.path as os
  9. import app
  10. import time
  11. import locale
  12. from fstools import *
  13. from ntfs import *
  14. from ue_con import *
  15. print 'Application initialized.'
  16.  
  17. def p_unicode(s):
  18.     return unicode(s, locale.getpreferredencoding())
  19.  
  20.  
  21. class CScanMgr:
  22.     
  23.     def __init__(self):
  24.         self._CScanMgr__active_scanners = { }
  25.         self._CScanMgr__mgr_lock = threading.Lock()
  26.  
  27.     
  28.     def add_scanner(self, scanner):
  29.         self._CScanMgr__mgr_lock.acquire()
  30.         self._CScanMgr__active_scanners[scanner] = scanner
  31.         self._CScanMgr__mgr_lock.release()
  32.  
  33.     
  34.     def finish_scanner(self, scanner):
  35.         self._CScanMgr__mgr_lock.acquire()
  36.         if self._CScanMgr__active_scanners.has_key(scanner):
  37.             del self._CScanMgr__active_scanners[scanner]
  38.         
  39.         self._CScanMgr__mgr_lock.release()
  40.  
  41.     
  42.     def _lock_all(self):
  43.         for scanner in self._CScanMgr__active_scanners.values():
  44.             scanner.lock()
  45.         
  46.  
  47.     
  48.     def _unlock_all(self):
  49.         for scanner in self._CScanMgr__active_scanners.values():
  50.             scanner.unlock()
  51.         
  52.  
  53.     
  54.     def interlocked_call(self, callable, *args, **kwargs):
  55.         '''
  56.             Blocks all scanners, execute callable
  57.             and unlocks scanners
  58.         '''
  59.         self._CScanMgr__mgr_lock.acquire()
  60.         self._lock_all()
  61.         
  62.         try:
  63.             callable(*args, **kwargs)
  64.         finally:
  65.             self._unlock_all()
  66.             self._CScanMgr__mgr_lock.release()
  67.  
  68.  
  69.     
  70.     def find_scanner_for_drive(self, drive_name):
  71.         '''
  72.             search scanner for drive, pause it,
  73.             and return result
  74.         '''
  75.         result = None
  76.         self._CScanMgr__mgr_lock.acquire()
  77.         self._lock_all()
  78.         for scanner in self._CScanMgr__active_scanners.values():
  79.             if scanner.drive_name == drive_name:
  80.                 result = scanner
  81.                 break
  82.                 continue
  83.         
  84.         for scanner in self._CScanMgr__active_scanners.values():
  85.             if scanner != result:
  86.                 scanner.unlock()
  87.                 continue
  88.         
  89.         self._CScanMgr__mgr_lock.release()
  90.         return result
  91.  
  92.     active_scanners = property((lambda self: self._CScanMgr__active_scanners.copy()))
  93.  
  94. ScanMgr = CScanMgr()
  95.  
  96. def update_quickview():
  97.     app.SetQVCaption(STR_NOT_AVAIL)
  98.     FF = app.GetFocusedFile()
  99.     if FF:
  100.         
  101.         try:
  102.             mft_ref = app.EntryGetMFTRef(FF)
  103.             Volume = app.VolumeForEntry(FF)
  104.             CurrentQVFile = Volume.open_file(mft_ref)
  105.         except Exception:
  106.             Value = None
  107.             traceback.print_exc()
  108.             CurrentQVFile = None
  109.  
  110.         if CurrentQVFile:
  111.             RC = CurrentQVFile.default_data_stream_size >> 4
  112.             if CurrentQVFile.default_data_stream_size & 3:
  113.                 RC += 1
  114.             
  115.             if RC > 4096:
  116.                 RC = 4095
  117.             
  118.             app.SetQVCaption(CurrentQVFile.win32_file_names.keys()[0])
  119.             C = RC * 16
  120.             if C > CurrentQVFile.default_data_stream_size:
  121.                 C = CurrentQVFile.default_data_stream_size
  122.             
  123.             if C > 0:
  124.                 
  125.                 try:
  126.                     data = CurrentQVFile.data_streams[''].read_data(0, C)
  127.                     app.SetQVData(data)
  128.                     app.SetQVRowCount(RC)
  129.                 except Exception:
  130.                     Value = None
  131.                     traceback.print_exc()
  132.                 except:
  133.                     None<EXCEPTION MATCH>Exception
  134.                 
  135.  
  136.             None<EXCEPTION MATCH>Exception
  137.             app.SetQVRowCount(0)
  138.             return None
  139.         
  140.     
  141.  
  142.  
  143. class CNTFSBaseScanner:
  144.     
  145.     def __init__(self, drive_name, device_name = None):
  146.         self._CNTFSBaseScanner__drive_name = drive_name
  147.         self._CNTFSBaseScanner__device_name = device_name
  148.         self._CNTFSBaseScanner__finish_event = threading.Event()
  149.         self._CNTFSBaseScanner__scanner_lock = threading.Lock()
  150.         self._CNTFSBaseScanner__finished = False
  151.         self._CNTFSBaseScanner__locked = False
  152.  
  153.     drive_name = property((lambda self: self._CNTFSBaseScanner__drive_name))
  154.     finish_event = property((lambda self: self._CNTFSBaseScanner__finish_event))
  155.     finished = property((lambda self: self._CNTFSBaseScanner__finished))
  156.     locked = property((lambda self: self._CNTFSBaseScanner__locked))
  157.     
  158.     def lock(self):
  159.         self._CNTFSBaseScanner__scanner_lock.acquire()
  160.         self._CNTFSBaseScanner__locked = True
  161.  
  162.     
  163.     def unlock(self):
  164.         if not self._CNTFSBaseScanner__locked:
  165.             raise AssertionError
  166.         self._CNTFSBaseScanner__locked = False
  167.         self._CNTFSBaseScanner__scanner_lock.release()
  168.  
  169.     
  170.     def run(self):
  171.         ScanMgr.add_scanner(self)
  172.         thread.start_new_thread(self._CNTFSBaseScanner__run, ())
  173.  
  174.     
  175.     def on_drive_open_error(self, ExceptionValue):
  176.         pass
  177.  
  178.     
  179.     def on_volume_open_error(self, ExceptionValue):
  180.         pass
  181.  
  182.     
  183.     def on_open_volume(self, VolumeObject):
  184.         pass
  185.  
  186.     
  187.     def on_open_entry_error(self, mft_ref, ExceptionValue):
  188.         pass
  189.  
  190.     
  191.     def on_open_entry_ok(self, mft_ref, file_object):
  192.         pass
  193.  
  194.     
  195.     def on_scan_finish(self):
  196.         pass
  197.  
  198.     
  199.     def __run(self):
  200.         print 'Base scanner: start scanning device ', self._CNTFSBaseScanner__device_name
  201.         drive_name = self._CNTFSBaseScanner__device_name
  202.         if not drive_name:
  203.             drive_name = self._CNTFSBaseScanner__drive_name
  204.         
  205.         
  206.         try:
  207.             drive = CreateCCachedDisk(CreateCOSDisk(drive_name), 7, 64)
  208.         except Exception:
  209.             Value = None
  210.             print 'Base scanner: drive opening error: ', Value
  211.             traceback.print_exc()
  212.             self.on_drive_open_error(Value)
  213.             ScanMgr.finish_scanner(self)
  214.             return None
  215.  
  216.         
  217.         try:
  218.             volume = CNTFSVolume(drive, 0, drive.sector_count)
  219.             volume.initialize()
  220.         except Exception:
  221.             Value = None
  222.             print 'Base scanner: volume opening error: ', Value
  223.             traceback.print_exc()
  224.             self.on_volume_open_error(Value)
  225.             ScanMgr.finish_scanner(self)
  226.             return None
  227.  
  228.         print 'Base scanner: volume opened successfully'
  229.         self.on_open_volume(volume)
  230.         RC = volume.MFT.mft_record_count
  231.         print 'Base scanner: start scanning for %s $MFT records' % RC
  232.         i = 0x0L
  233.         acq = self._CNTFSBaseScanner__scanner_lock.acquire
  234.         rel = self._CNTFSBaseScanner__scanner_lock.release
  235.         while i < RC:
  236.             acq()
  237.             
  238.             try:
  239.                 file = volume.open_file_if_base(i)
  240.             except Exception:
  241.                 Value = None
  242.                 self.on_open_entry_error(i, Value)
  243.                 i += 1
  244.                 rel()
  245.                 continue
  246.  
  247.             
  248.             try:
  249.                 self.on_open_entry_ok(i, file)
  250.             finally:
  251.                 rel()
  252.  
  253.             i += 1
  254.         print 'Base scanner: scanning process complete'
  255.         self.on_scan_finish()
  256.         self.finish_event.set()
  257.         ScanMgr.finish_scanner(self)
  258.  
  259.  
  260.  
  261. class CNTFSVisualScanner(CNTFSBaseScanner):
  262.     
  263.     def __init__(self, volume_entry):
  264.         self._CNTFSVisualScanner__volume_entry = volume_entry
  265.         drive_name = app.EntryGetName(volume_entry)
  266.         device_name = u'\\\\.\\%s' % drive_name
  267.         self._CNTFSVisualScanner__unk_folder = None
  268.         CNTFSBaseScanner.__init__(self, drive_name, device_name)
  269.  
  270.     unk_folder = property((lambda self: self._CNTFSVisualScanner__unk_folder))
  271.     volume_entry = property((lambda self: self._CNTFSVisualScanner__volume_entry))
  272.     
  273.     def on_open_volume(self, VolumeObject):
  274.         app.EntrySetUserFlag(self._CNTFSVisualScanner__volume_entry, 0, 1)
  275.         app.SetupVolumeObject(self._CNTFSVisualScanner__volume_entry, VolumeObject)
  276.         app.SetScanPercent(self._CNTFSVisualScanner__volume_entry, 0)
  277.         self._CNTFSVisualScanner__unk_folder = app.AddDirectoryEntry(self._CNTFSVisualScanner__volume_entry, -0x7L, 0, u'Lost Files and Folders', 1, 0, 0)
  278.         self._CNTFSVisualScanner__folders = [ None for i in xrange(VolumeObject.MFT.mft_record_count) ]
  279.         self._CNTFSVisualScanner__volume = VolumeObject
  280.         self._CNTFSVisualScanner__tmp_old_oade = self.on_add_directory_entry
  281.         self.on_add_directory_entry = self._CNTFSVisualScanner__on_first_dir_entry
  282.         app.ShowScanDlg(self._CNTFSVisualScanner__volume_entry)
  283.  
  284.     
  285.     def on_drive_open_error(self, ExceptionValue):
  286.         app.ShowMessageModal(STR_DRV_ACCES_ERROR % str(ExceptionValue))
  287.  
  288.     
  289.     def on_volume_open_error(self, ExceptionValue):
  290.         app.ShowMessageModal(STR_CANNOT_OPEN_NTFS_VOLUME)
  291.         print ExceptionValue
  292.         traceback.print_exc()
  293.  
  294.     
  295.     def on_open_entry_error(self, mft_ref, ExceptionValue):
  296.         pass
  297.  
  298.     
  299.     on_add_file_entry = lambda self, entry, entry_to: pass
  300.     
  301.     on_move_entry = lambda self, entry, entry_to: pass
  302.     
  303.     on_add_directory_entry = lambda self, entry, entry_to: pass
  304.     
  305.     def __on_first_dir_entry(self, entry, entry_to):
  306.         app.ExpandEntryEx(self._CNTFSVisualScanner__volume_entry)
  307.         self.on_add_directory_entry = self._CNTFSVisualScanner__tmp_old_oade
  308.         return self._CNTFSVisualScanner__tmp_old_oade(entry, entry_to)
  309.  
  310.     
  311.     def on_open_entry_ok(self, mft_ref, file):
  312.         if mft_ref == 5:
  313.             return None
  314.         
  315.         folders = self._CNTFSVisualScanner__folders
  316.         (creation_time, last_data_change_time, last_access_time, last_mft_change_time, file_attributes) = file.get_standard_info()
  317.         CD = app.NTFSDate2DateTime(creation_time)
  318.         MD = app.NTFSDate2DateTime(last_data_change_time)
  319.         for file_name, file_name_attr in file.win32_file_names.items():
  320.             parent_ref = file_name_attr.get_parent_directory() & 0xFFFFFFFFFFFFL
  321.             if parent_ref >= len(folders):
  322.                 continue
  323.             
  324.             if parent_ref != 5:
  325.                 parent_folder = folders[parent_ref]
  326.             else:
  327.                 parent_folder = self._CNTFSVisualScanner__volume_entry
  328.             if parent_folder is None:
  329.                 parent_folder = app.AddDirectoryEntry(self._CNTFSVisualScanner__unk_folder, parent_ref, 0, u'', 1, 0, 0)
  330.                 folders[parent_ref] = parent_folder
  331.                 self.on_add_directory_entry(parent_folder, self._CNTFSVisualScanner__unk_folder)
  332.             
  333.             if file.is_directory:
  334.                 fld = folders[mft_ref]
  335.                 if fld:
  336.                     app.NotifyChangeEntry(fld, file_name, CD, MD, file.is_deleted)
  337.                     app.MoveEntry(fld, parent_folder)
  338.                     self.on_move_entry(fld, parent_folder)
  339.                 else:
  340.                     folders[mft_ref] = entry = app.AddDirectoryEntry(parent_folder, mft_ref, file.data_stream_count, file_name, file.is_deleted, CD, MD)
  341.                     self.on_add_directory_entry(entry, parent_folder)
  342.             fld
  343.             entry = app.AddFileEntry(parent_folder, mft_ref, file.default_data_stream_size, file.data_stream_count, file_name, file.is_deleted, CD, MD)
  344.             self.on_add_file_entry(entry, parent_folder)
  345.         
  346.         if mft_ref % 256 == 0:
  347.             percent = int(mft_ref * 100.0 / self._CNTFSVisualScanner__volume.MFT.mft_record_count)
  348.             app.SetScanPercent(self._CNTFSVisualScanner__volume_entry, percent)
  349.             print 'SCAN: ', self.drive_name, mft_ref, ' entries processed\r',
  350.         
  351.  
  352.     
  353.     def on_scan_finish(self):
  354.         app.SetScanPercent(self._CNTFSVisualScanner__volume_entry, 100)
  355.         app.HideScanDlg()
  356.  
  357.  
  358.  
  359. def scan_drive():
  360.     print 'Starting scan.'
  361.     CNTFSVisualScanner(app.GetCWD()).run()
  362.  
  363.  
  364. def internal_object_report():
  365.     report = u'\n    <html>\n    <head>\n        <link rel=stylesheet href="file://%s//reports-style.css" type="text/css">\n    </head>\n    <body>\n        <p>Internal object. No properties available.</p>    \n    </body>\n    </html>\n    '
  366.     return report % p_unicode(os.getcwd())
  367.  
  368.  
  369. def make_properties_report(volume, mft_ref):
  370.     if mft_ref < 0:
  371.         return internal_object_report()
  372.     
  373.     general_info_template = STR_GENERAL_INFO_TEMPLATE
  374.     file = CNTFSFile(volume, mft_ref)
  375.     file.open()
  376.     is_deleted = 'No'
  377.     if file.is_deleted:
  378.         is_deleted = 'Yes'
  379.     
  380.     MFTRecords = ''
  381.     j = 1
  382.     for i in file.mft_refs:
  383.         MFTRecords = MFTRecords + '<tr><td>MFT#%i</td><td>%s</td></tr>' % (j, i)
  384.         j += 1
  385.     
  386.     general_info = general_info_template % (p_unicode(os.getcwd()), mft_ref, volume.path_for_mft_ref(mft_ref)[:-1], file.data_stream_count, is_deleted, len(file.mft_records), MFTRecords)
  387.     return general_info
  388.  
  389. SearchActive = False
  390. search_lock = threading.Lock()
  391.  
  392. class CSearchScanMixin:
  393.     
  394.     def __init__(self, scanner, validation_cb, finish_evt, recurse_search_cb):
  395.         self._CSearchScanMixin__scanner = scanner
  396.         self._CSearchScanMixin__validation_cb = validation_cb
  397.         self._CSearchScanMixin__recurse_search_cb = recurse_search_cb
  398.         self._CSearchScanMixin__finish_evt = finish_evt
  399.  
  400.     scanner = property((lambda self: self._CSearchScanMixin__scanner))
  401.     
  402.     def __check_activity(self):
  403.         if not SearchActive:
  404.             self.detach_mixin()
  405.             self._CSearchScanMixin__finish_evt.set()
  406.             return False
  407.         
  408.         return True
  409.  
  410.     
  411.     def __on_add_file_entry(self, entry, entry_to):
  412.         self._old_on_add_file_entry(entry, entry_to)
  413.         if self._CSearchScanMixin__check_activity():
  414.             if not app.EntryHasUnkEntryParent(entry):
  415.                 self._CSearchScanMixin__validation_cb(entry)
  416.             
  417.         
  418.  
  419.     
  420.     def __on_drive_open_error(self, ExceptionValue):
  421.         self._CSearchScanMixin__finish_evt.set()
  422.  
  423.     
  424.     def __on_volume_open_error(self, ExceptionValue):
  425.         self._CSearchScanMixin__finish_evt.set()
  426.  
  427.     
  428.     def __on_add_directory_entry(self, entry, entry_to):
  429.         self._old_on_add_directory_entry(entry, entry_to)
  430.         if self._CSearchScanMixin__check_activity():
  431.             if not app.EntryHasUnkEntryParent(entry):
  432.                 self._CSearchScanMixin__validation_cb(entry)
  433.             
  434.         
  435.  
  436.     
  437.     def __on_move_entry(self, entry, entry_to):
  438.         self._old_on_move_entry(entry, entry_to)
  439.         if self._CSearchScanMixin__check_activity():
  440.             if not app.EntryHasUnkEntryParent(entry):
  441.                 self._CSearchScanMixin__recurse_search_cb(entry)
  442.             
  443.         
  444.  
  445.     
  446.     def __on_scan_finish(self):
  447.         self._old_on_scan_finish()
  448.         self._CSearchScanMixin__finish_evt.set()
  449.  
  450.     
  451.     def attach_mixin(self, scanner, *args):
  452.         mixin = self(scanner, *args)
  453.         mixin._old_on_add_file_entry = scanner.on_add_file_entry
  454.         mixin._old_on_add_directory_entry = scanner.on_add_directory_entry
  455.         mixin._old_on_move_entry = scanner.on_move_entry
  456.         mixin._old_on_scan_finish = scanner.on_scan_finish
  457.         mixin._old_on_drive_open_error = scanner.on_drive_open_error
  458.         mixin._old_on_volume_open_error = scanner.on_volume_open_error
  459.         scanner.on_add_file_entry = mixin._CSearchScanMixin__on_add_file_entry
  460.         scanner.on_add_directory_entry = mixin._CSearchScanMixin__on_add_directory_entry
  461.         scanner.on_move_entry = mixin._CSearchScanMixin__on_move_entry
  462.         scanner.on_scan_finish = mixin._CSearchScanMixin__on_scan_finish
  463.         scanner.on_drive_open_error = mixin._CSearchScanMixin__on_drive_open_error
  464.         scanner.on_volume_open_error = mixin._CSearchScanMixin__on_volume_open_error
  465.         return mixin
  466.  
  467.     attach_mixin = classmethod(attach_mixin)
  468.     
  469.     def detach_mixin(self):
  470.         scanner = self.scanner
  471.         scanner.on_add_file_entry = self._old_on_add_file_entry
  472.         scanner.on_add_directory_entry = self._old_on_add_directory_entry
  473.         scanner.on_move_entry = self._old_on_move_entry
  474.         scanner.on_drive_open_error = self._old_on_drive_open_error
  475.         scanner.on_volume_open_error = self._old_on_volume_open_error
  476.  
  477.  
  478.  
  479. def search_files():
  480.     FoundResults = 0x0L
  481.     
  482.     def do_search():
  483.         global FoundResults
  484.         app.InitSearch()
  485.         FoundResults = 0x0L
  486.         search_params = app.GetSearchParams()
  487.         look_in = search_params['look_in']
  488.         if type(look_in) != type(1):
  489.             _do_search(look_in)
  490.         else:
  491.             root = app.GetRootEntry()
  492.             entry = app.EntryGetFirstChild(root)
  493.             while entry:
  494.                 if app.EntryIsDrive(entry):
  495.                     _do_search(entry)
  496.                 
  497.                 entry = app.EntryGetNext(entry)
  498.         app.DoneSearch()
  499.         app.ShowMessageModal(STR_SEARCH_COMPLETE % FoundResults)
  500.  
  501.     
  502.     def _do_search(search_start_entry):
  503.         global SearchActive, FoundResults
  504.         print 'Search start...'
  505.         SearchActive = True
  506.         search_params = app.GetSearchParams()
  507.         masks = map((lambda x: x.strip()), search_params['masks'].split(','))
  508.         case_sensitive = search_params['case_sensitive']
  509.         search_folders = search_params['search_folders']
  510.         search_files = search_params['search_files']
  511.         search_deleted = search_params['deleted_entries']
  512.         search_non_deleted = search_params['non_deleted_entries']
  513.         use_modify_filter = search_params['use_modify_filter']
  514.         modify_from = None
  515.         modify_to = None
  516.         if use_modify_filter:
  517.             modify_from = search_params['modify_from']
  518.             modify_to = search_params['modify_to']
  519.         
  520.         use_create_filter = search_params['use_create_filter']
  521.         created_from = None
  522.         created_to = None
  523.         if use_create_filter:
  524.             created_from = search_params['created_from']
  525.             created_to = search_params['created_to']
  526.         
  527.         if not case_sensitive:
  528.             masks = map((lambda mask: mask.upper()), masks)
  529.         
  530.         size_from = search_params.get('size_from', None)
  531.         if size_from:
  532.             (a, b) = tuple(filter((lambda x: x != ''), size_from.split(' ')))
  533.             size_from = long(a)
  534.             if b == 'KB':
  535.                 size_from *= 0x400L
  536.             elif b == 'MB':
  537.                 size_from *= 0x400L * 0x400L
  538.             elif b == 'GB':
  539.                 size_from *= 0x400L * 0x400L * 0x400L
  540.             
  541.         
  542.         size_to = search_params.get('size_to', None)
  543.         if size_to:
  544.             (a, b) = tuple(filter((lambda x: x != ''), size_to.split(' ')))
  545.             size_to = long(a)
  546.             if b == 'KB':
  547.                 size_to *= 0x400L
  548.             elif b == 'MB':
  549.                 size_to *= 0x400L * 0x400L
  550.             elif b == 'GB':
  551.                 size_to *= 0x400L * 0x400L * 0x400L
  552.             
  553.         
  554.         _entries = { }
  555.         
  556.         def _validate_entry(entry):
  557.             name = app.EntryGetName(entry)
  558.             if not case_sensitive:
  559.                 name = name.upper()
  560.             
  561.             for mask in masks:
  562.                 if mask == '*.*':
  563.                     mask = '*'
  564.                 
  565.                 if not app.FileNameMatches(name, unicode(mask)):
  566.                     continue
  567.                 
  568.                 if not (search_files or app.EntryIsFile(entry)) and search_folders and app.EntryIsDirectory(entry):
  569.                     continue
  570.                 
  571.                 if not (search_deleted or app.EntryIsDeleted(entry)) and search_non_deleted and not app.EntryIsDeleted(entry):
  572.                     continue
  573.                 
  574.                 if use_modify_filter:
  575.                     MD = app.EntryGetModifyDate(entry)
  576.                     if not MD >= modify_from and MD < modify_to + 1:
  577.                         continue
  578.                     
  579.                 
  580.                 if use_create_filter:
  581.                     CD = app.EntryGetCreateDate(entry)
  582.                     if not CD >= created_from and CD < created_to + 1:
  583.                         continue
  584.                     
  585.                 
  586.                 if size_from is not None and app.EntryIsFile(entry):
  587.                     if not app.EntryGetDataSize(entry) >= size_from:
  588.                         continue
  589.                     
  590.                 
  591.                 if size_to is not None and app.EntryIsFile(entry):
  592.                     if not app.EntryGetDataSize(entry) <= size_to:
  593.                         continue
  594.                     
  595.                 
  596.                 mft_ref = app.EntryGetMFTRef(entry)
  597.                 if not _entries.has_key(mft_ref):
  598.                     app.AddSearchResult(entry)
  599.                     _entries[mft_ref] = entry
  600.                 
  601.                 break
  602.             
  603.  
  604.         
  605.         def _caption_thread(evt):
  606.             while True:
  607.                 for i in xrange(6):
  608.                     evt.wait(0.5)
  609.                     if evt.isSet():
  610.                         return None
  611.                     
  612.                     app.SetSearchCaption(u'Searching ' + u'.' * i)
  613.                 
  614.  
  615.         skip_unk_entry = False
  616.         
  617.         def _search_from(entry):
  618.             while entry and SearchActive:
  619.                 _validate_entry(entry)
  620.                 if app.EntryIsContainer(entry):
  621.                     if skip_unk_entry and app.EntryIsDirectory(entry) and app.EntryGetMFTRef(entry) == -7:
  622.                         entry = app.EntryGetNext(entry)
  623.                         continue
  624.                     
  625.                     _search_from(app.EntryGetFirstChild(entry))
  626.                 
  627.                 entry = app.EntryGetNext(entry)
  628.  
  629.         
  630.         def _recurse_search(entry):
  631.             if entry:
  632.                 _validate_entry(entry)
  633.                 _search_from(app.EntryGetFirstChild(entry))
  634.             
  635.  
  636.         search_finished = threading.Event()
  637.         
  638.         def __on_search_init_error(ExceptionValue):
  639.             search_finished.set()
  640.             app.ShowMessageModal(STR_NON_NTFS_DRIVE % (app.EntryGetName(search_start_entry),))
  641.  
  642.         entry_name = app.EntryGetName(search_start_entry)
  643.         search_lock.acquire()
  644.         if app.EntryIsDriveNotScanned(search_start_entry):
  645.             scanner = CNTFSVisualScanner(search_start_entry)
  646.             scanner.on_drive_open_error = __on_search_init_error
  647.             scanner.on_volume_open_error = __on_search_init_error
  648.             scanner.run()
  649.         
  650.         search_lock.release()
  651.         scanner = ScanMgr.find_scanner_for_drive(entry_name)
  652.         thread.start_new_thread(_caption_thread, (search_finished,))
  653.         if scanner is None:
  654.             _recurse_search(search_start_entry)
  655.             search_finished.set()
  656.         else:
  657.             skip_unk_entry = True
  658.             _recurse_search(search_start_entry)
  659.             skip_unk_entry = False
  660.             CSearchScanMixin.attach_mixin(scanner, _validate_entry, search_finished, _search_from)
  661.             scanner.unlock()
  662.             search_finished.wait()
  663.             _recurse_search(scanner.unk_folder)
  664.         print '\n\nFOUND: ', app.GetSearchResultCount()
  665.         FoundResults += app.GetSearchResultCount()
  666.  
  667.     thread.start_new_thread(do_search, ())
  668.  
  669.  
  670. def cancel_search():
  671.     global SearchActive
  672.     SearchActive = False
  673.  
  674.  
  675. def get_checked_entries():
  676.     result = []
  677.     
  678.     def recurse_process(entry):
  679.         if app.EntryIsChecked(entry):
  680.             result.append(entry)
  681.             if app.EntryIsContainer(entry):
  682.                 entry = app.EntryGetFirstChild(entry)
  683.                 while entry:
  684.                     recurse_process(entry)
  685.                     entry = app.EntryGetNext(entry)
  686.             
  687.         
  688.  
  689.     recurse_process(app.GetRootEntry())
  690.     return result
  691.  
  692.  
  693. def local_path_for_entry(entry):
  694.     if app.EntryIsDrive(entry):
  695.         return app.EntryGetName(entry)[0]
  696.     
  697.     parent = app.EntryGetParent(entry)
  698.     if parent:
  699.         return local_path_for_entry(parent) + u'\\' + app.EntryGetName(entry)
  700.     else:
  701.         return u''
  702.  
  703.  
  704. def real_path_for_entry(entry):
  705.     parent = app.EntryGetParent(entry)
  706.     if parent:
  707.         return real_path_for_entry(parent) + u'\\' + app.EntryGetName(entry)
  708.     else:
  709.         return u''
  710.  
  711.  
  712. def get_entry_parents(entry):
  713.     R = []
  714.     p = app.EntryGetParent(entry)
  715.     while p:
  716.         R.append(p)
  717.         p = app.EntryGetParent(p)
  718.     return R
  719.  
  720.  
  721. def get_minimal_common_parent_id(file_entries):
  722.     c = { }
  723.     d = { }
  724.     for e in file_entries:
  725.         parents = get_entry_parents(e)
  726.         dpt = len(parents)
  727.         for parent in parents:
  728.             pid = app.EntryGetID(parent)
  729.             d[pid] = dpt
  730.             dpt -= 1
  731.             if c.has_key(pid):
  732.                 c[pid] += 1
  733.                 continue
  734.             c[pid] = 1
  735.         
  736.     
  737.     items = [ (b, d[a], a) for a, b in c.items() ]
  738.     items.sort()
  739.     mpid = -0x1L
  740.     return mpid
  741.  
  742.  
  743. def path_upto_parent(entry, parent_id):
  744.     parent = app.EntryGetParent(entry)
  745.     if parent and app.EntryGetID(parent) != parent_id:
  746.         pp = path_upto_parent(parent, parent_id)
  747.         if pp:
  748.             return pp + u'\\' + app.EntryGetName(entry)
  749.         else:
  750.             return app.EntryGetName(entry)
  751.     elif parent:
  752.         if not app.EntryIsDrive(entry):
  753.             return app.EntryGetName(entry)
  754.         else:
  755.             return app.EntryGetName(entry)[0]
  756.     else:
  757.         return u''
  758.  
  759. RecoveryRunning = False
  760. RecoverySkip = False
  761. rmtMessage = 1
  762. rmtError = 2
  763. rmtWarning = 3
  764. rmtSuccess = 4
  765.  
  766. def start_recovery():
  767.     
  768.     class RecoveryContext:
  769.         
  770.         def __init__(self):
  771.             self.total_files = 0
  772.             self.total_size = 0x0L
  773.             self.processed_files = 0
  774.             self.processed_size = 0x0L
  775.             self.current_file_name = u''
  776.             self.current_file_progress = 0
  777.  
  778.  
  779.     
  780.     def emit(cls, s):
  781.         app.EmitRecoveryMessage(cls, s)
  782.  
  783.     
  784.     def generate_autoname(path):
  785.         for i in xrange(1000):
  786.             fname = path + u'#' + str(i)
  787.             if not os.path.exists(fname):
  788.                 return fname
  789.                 continue
  790.         
  791.         raise Exception('Unable to generate file name for ' + path)
  792.  
  793.     
  794.     def uprecurse_uncheck(entry):
  795.         app.UnmarkEntry(entry)
  796.         parent = app.EntryGetParent(entry)
  797.         if parent and not app.EntryHasMarkedChildren(parent):
  798.             app.UnmarkEntry(parent)
  799.             uprecurse_uncheck(parent)
  800.         
  801.  
  802.     
  803.     def copy_file(entry, target_path, context, rparams):
  804.         global RecoverySkip
  805.         recover_all_data_strems = rparams['recover_all_data_strems']
  806.         delete_unsuccessful = rparams['delete_unsuccessful']
  807.         naming = rparams['naming']
  808.         unchecking = rparams['unchecking']
  809.         context.current_file_progress = 0
  810.         RecoverySkip = False
  811.         BULK = 256 * 1024
  812.         processed_size = 0x0L
  813.         total_size = 0x0L
  814.         file_name = None
  815.         has_errors = False
  816.         f = None
  817.         
  818.         try:
  819.             volume = app.VolumeForEntry(entry)
  820.             mft_ref = app.EntryGetMFTRef(entry)
  821.             if volume and mft_ref >= 0:
  822.                 file = volume.open_file(mft_ref)
  823.                 if len(file.data_streams) > 1:
  824.                     emit(rmtMessage, STR_KNOWN_DATA_STREAMS + unicode(str(file.data_streams.keys())))
  825.                 
  826.                 total_size = reduce((lambda x, y: y.size + x), file.data_streams.values(), 0x0L)
  827.                 for data_stream_name, data_stream in file.data_streams.items():
  828.                     is_alter_stream = len(data_stream_name) > 0
  829.                     if is_alter_stream and not recover_all_data_strems:
  830.                         continue
  831.                     
  832.                     if data_stream_name:
  833.                         context.current_file_name = app.EntryGetName(entry) + u' stream: ' + data_stream_name
  834.                     else:
  835.                         context.current_file_name = app.EntryGetName(entry)
  836.                     file_name = target_path
  837.                     if data_stream_name:
  838.                         file_name += u'_' + data_stream_name
  839.                     
  840.                     if os.path.exists(file_name):
  841.                         if naming == 0:
  842.                             file_name = generate_autoname(file_name)
  843.                         elif naming == 1:
  844.                             file_name = app.SaveDlgQuery(file_name)
  845.                             if not file_name:
  846.                                 raise Exception(STR_USER_SKIPPED)
  847.                             
  848.                         elif naming == 2:
  849.                             continue
  850.                         
  851.                     
  852.                     f = open(file_name, 'wb')
  853.                     pos = 0x0L
  854.                     count = data_stream.size
  855.                     while count > 0:
  856.                         if not RecoveryRunning:
  857.                             raise Exception(STR_USER_CANCELLED)
  858.                         
  859.                         if RecoverySkip:
  860.                             if not is_alter_stream:
  861.                                 context.processed_size += count
  862.                             
  863.                             raise Exception(STR_USER_SKIPPED)
  864.                         
  865.                         C = BULK
  866.                         if C > count:
  867.                             C = count
  868.                         
  869.                         
  870.                         try:
  871.                             data = data_stream.read_data(pos, C)
  872.                             pos += C
  873.                             count -= C
  874.                             processed_size += C
  875.                             context.current_file_progress = int(processed_size * 100.0 / total_size)
  876.                             f.write(data)
  877.                         finally:
  878.                             pass
  879.  
  880.                     f.close()
  881.                     f = None
  882.                     if is_alter_stream:
  883.                         emit(rmtSuccess, u'Recovered ok - ' + app.EntryGetPath(entry) + u' stream ' + data_stream_name)
  884.                         continue
  885.                     emit(rmtSuccess, u'Recovered ok - ' + app.EntryGetPath(entry))
  886.                 
  887.             else:
  888.                 raise Exception(STR_CANNOT_OPEN_FILE % (mft_ref, str(volume)))
  889.         except Exception:
  890.             Value = None
  891.             has_errors = True
  892.             emit(rmtError, STR_ERROR_ON % (target_path, str(Value)))
  893.             if f:
  894.                 f.close()
  895.             
  896.             if file_name and delete_unsuccessful:
  897.                 
  898.                 try:
  899.                     os.remove(file_name)
  900.                 except Exception:
  901.                     Value = None
  902.                 except:
  903.                     None<EXCEPTION MATCH>Exception
  904.                 
  905.  
  906.             None<EXCEPTION MATCH>Exception
  907.  
  908.         context.processed_files += 1
  909.         if unchecking == 0 or not has_errors or unchecking == 1:
  910.             uprecurse_uncheck(entry)
  911.         
  912.  
  913.     
  914.     def report_thread(context):
  915.         while RecoveryRunning:
  916.             if context.total_size:
  917.                 total_progress = int(context.processed_size * 100.0 / context.total_size)
  918.                 if total_progress > 100:
  919.                     total_progress = 100
  920.                 
  921.                 app.NotifyRecoveryProgress(context.current_file_name, context.current_file_progress, total_progress, context.total_files, context.processed_files, context.total_files - context.processed_files, u'unknown', u'unknown', u'unknown')
  922.             
  923.             time.sleep(0.10000000000000001)
  924.         app.NotifyRecoveryProgress(context.current_file_name, context.current_file_progress, 100, context.total_files, context.processed_files, context.total_files - context.processed_files, u'unknown', u'unknown', u'unknown')
  925.         app.RecoveryPanelDone()
  926.  
  927.     
  928.     def recovery():
  929.         global RecoveryRunning, total_files, RecoveryRunning
  930.         RecoveryRunning = True
  931.         
  932.         try:
  933.             app.RecoveryPanelInit()
  934.             rparams = app.GetRecoveryParams()
  935.             recover_folder_structure = rparams['recover_folder_structure']
  936.             dst_folder = rparams['recovery_folder']
  937.             if not os.path.exists(dst_folder):
  938.                 
  939.                 try:
  940.                     os.makedirs(dst_folder)
  941.                 S = STR_CANNOT_CREATE_FOLDER + dst_folder
  942.                 app.ShowMessageModal(S)
  943.                 raise Exception(S)
  944.  
  945.             
  946.             c = dst_folder[-1]
  947.             if c != '\\' and c != '/':
  948.                 dst_folder += '\\'
  949.             
  950.             _drv = os.path.abspath(dst_folder)[:2]
  951.             emit(rmtMessage, STR_START_RECOVERY_TO + dst_folder)
  952.             emit(rmtMessage, STR_GEN_FILE_LIST)
  953.             entries = get_checked_entries()
  954.             files = filter((lambda entry: app.EntryIsFile(entry)), entries)
  955.             mcpid = get_minimal_common_parent_id(files)
  956.             total_files = len(files)
  957.             total_size = reduce((lambda x, y: app.EntryGetDataSize(y) + x), files, 0x0L)
  958.             emit(rmtMessage, STR_FILE_LIST_GENERATED % (len(entries), total_files, total_size))
  959.             context = RecoveryContext()
  960.             context.total_files = total_files
  961.             context.total_size = total_size
  962.             thread.start_new_thread(report_thread, (context,))
  963.             for fe in entries:
  964.                 if app.EntryGetPath(fe)[:2].upper() == _drv.upper():
  965.                     if app.ShowYesNoDlg(u'It is not safe to recover some files into the folder you specified, recovered files can be corrupted. Do you want to proceed anyway?') == 7:
  966.                         raise Exception(STR_USER_CANCELLED)
  967.                     else:
  968.                         break
  969.                 app.ShowYesNoDlg(u'It is not safe to recover some files into the folder you specified, recovered files can be corrupted. Do you want to proceed anyway?') == 7
  970.             
  971.             if len(entries) > 0:
  972.                 del entries[0]
  973.                 for entry in files:
  974.                     if not RecoveryRunning:
  975.                         break
  976.                     
  977.                     full_path = None
  978.                     if recover_folder_structure:
  979.                         full_path = dst_folder + path_upto_parent(entry, mcpid)
  980.                     else:
  981.                         full_path = dst_folder + app.EntryGetName(entry)
  982.                     print 'UPTO PATH: ', path_upto_parent(entry, mcpid)
  983.                     dirs = u'\\'.join(full_path.split(u'\\')[:-1])
  984.                     if not os.path.exists(dirs):
  985.                         print 'Create dirs: ', dirs
  986.                         os.makedirs(dirs)
  987.                     
  988.                     copy_file(entry, full_path, context, rparams)
  989.                 
  990.         finally:
  991.             RecoveryRunning = False
  992.  
  993.  
  994.     thread.start_new_thread(recovery, ())
  995.  
  996.  
  997. def recovery_stop():
  998.     global RecoveryRunning
  999.     RecoveryRunning = False
  1000.  
  1001.  
  1002. def recovery_pause():
  1003.     app.ShowMessageModal(STR_RECOVERY_PAUSED)
  1004.  
  1005.  
  1006. def recovery_skip_current_file():
  1007.     global RecoverySkip
  1008.     RecoverySkip = True
  1009.  
  1010.  
  1011. def execute_script(script_path):
  1012.     
  1013.     def _doexec():
  1014.         execfile(script_path)
  1015.  
  1016.     thread.start_new_thread(_doexec, ())
  1017.  
  1018. progress_dlg_cancel = False
  1019.  
  1020. def save_as():
  1021.     
  1022.     def _do_save_as():
  1023.         global progress_dlg_cancel
  1024.         progress_dlg_cancel = False
  1025.         ff = app.GetFocusedFile()
  1026.         if ff:
  1027.             file_name = app.SaveDlgQuery(app.EntryGetName(ff))
  1028.             if not file_name:
  1029.                 return None
  1030.             
  1031.             file_name = os.path.abspath(file_name)
  1032.             if file_name[:2].upper() == app.EntryGetPath(ff)[:2].upper():
  1033.                 if app.ShowYesNoDlg(u'It is not safe to recover the file to destination you specified, recovered files can be corrupted. Do you want to proceed anyway?') == 7:
  1034.                     return None
  1035.                 
  1036.             
  1037.             if file_name:
  1038.                 BULK = 256 * 1024
  1039.                 app.ShowProgressDlg(u'Copy...', u'Copy file ' + app.EntryGetName(ff) + u' to ' + file_name)
  1040.                 entry = ff
  1041.                 target_path = file_name
  1042.                 
  1043.                 try:
  1044.                     volume = app.VolumeForEntry(entry)
  1045.                     mft_ref = app.EntryGetMFTRef(entry)
  1046.                     if volume and mft_ref >= 0:
  1047.                         file = volume.open_file(mft_ref)
  1048.                         total_size = reduce((lambda x, y: y.size + x), file.data_streams.values(), 0x0L)
  1049.                         processed_size = 0x0L
  1050.                         for data_stream_name, data_stream in file.data_streams.items():
  1051.                             is_alter_stream = len(data_stream_name) > 0
  1052.                             file_name = target_path
  1053.                             if data_stream_name:
  1054.                                 file_name += u'_' + data_stream_name
  1055.                             
  1056.                             f = open(file_name, 'wb')
  1057.                             pos = 0x0L
  1058.                             count = data_stream.size
  1059.                             while count > 0:
  1060.                                 if progress_dlg_cancel:
  1061.                                     raise Exception(STR_USER_CANCELLED)
  1062.                                 
  1063.                                 C = BULK
  1064.                                 if C > count:
  1065.                                     C = count
  1066.                                 
  1067.                                 data = data_stream.read_data(pos, C)
  1068.                                 pos += C
  1069.                                 count -= C
  1070.                                 processed_size += C
  1071.                                 f.write(data)
  1072.                                 perc = int(pos * 100.0 / data_stream.size)
  1073.                                 app.NotifyProgressDlg(perc)
  1074.                             f.close()
  1075.                         
  1076.                 except:
  1077.                     traceback.print_exc()
  1078.  
  1079.                 app.HideProgressDlg()
  1080.             
  1081.         
  1082.  
  1083.     thread.start_new_thread(_do_save_as, ())
  1084.  
  1085.  
  1086. def on_progress_dlg_cancel():
  1087.     global progress_dlg_cancel
  1088.     progress_dlg_cancel = True
  1089.  
  1090.  
  1091. def on_application_close():
  1092.     global RecoveryRunning, SearchActive, ScannerActive
  1093.     RecoveryRunning = False
  1094.     SearchActive = False
  1095.     ScannerActive = False
  1096.  
  1097.